package com.sise.netty.断线重连;

import com.sise.netty.断线重连.serialHandler.MarshallingCodeHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.timeout.ReadTimeoutHandler;

/**
 * @author idea
 * @data 2019/4/14
 */
public class Server {

    /**
     * 请求接收线程组
     */
    private EventLoopGroup acceptGroup = null;

    /**
     * 客户端线程组
     */
    private EventLoopGroup clientGroup = null;

    /**
     * 基础配置
     */
    private ServerBootstrap bootstrap = null;


    private void init() {
        acceptGroup = new NioEventLoopGroup();
        clientGroup = new NioEventLoopGroup();
        //配置需要进行绑定
        bootstrap = new ServerBootstrap();
        bootstrap.group(acceptGroup, clientGroup);
        //配置指定相应的通信方式是nio形式
        bootstrap.channel(NioServerSocketChannel.class);

        //指定缓冲区配置，心跳模式
        bootstrap.option(ChannelOption.SO_BACKLOG, 1024);
        bootstrap.option(ChannelOption.SO_SNDBUF, 16 * 1024)
                .option(ChannelOption.SO_RCVBUF, 16 * 1024)
                .option(ChannelOption.SO_KEEPALIVE, true);
    }

    public Server() {
        init();
    }

    public ChannelFuture doAccept(int port, ChannelHandler... acceptChannelHandler) throws InterruptedException {
        bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {

            //当新的客户端连接的时候，才会执行
            @Override
            protected void initChannel(SocketChannel ch) throws Exception {
                System.out.println("初始化通道信息");
                //定义编码器和解码器

                ch.pipeline().addLast(MarshallingCodeHandler.buildMarshallingDecoder());
                ch.pipeline().addLast(MarshallingCodeHandler.buildMarshallingEncoder());
                //定义一个定时断线处理器，当多长时间内没有任何的可读取数据就会自动断开
                ch.pipeline().addLast(new ReadTimeoutHandler(3));
                ch.pipeline().addLast(new ServerHandle());

            }
        });
        //bind的时候已经开始监听流程了，sync是为了让主线程监听流程处理完毕
        ChannelFuture future = bootstrap.bind(port).sync();
        return future;
    }

    /**
     * 释放掉两个线程组的资源
     */
    public void relase() {
        this.acceptGroup.shutdownGracefully();
        this.clientGroup.shutdownGracefully();
    }


    public static void main(String[] args) {
        ChannelFuture future = null;
        Server server = null;
        try {
            server = new Server();
            future = server.doAccept(9090, new ServerHandle());
            System.out.println("server is open");
            future.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (null != future) {
                try {
                    future.channel().closeFuture().sync();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            if (null != server) {
                server.relase();
            }
        }

    }


}
